
/*    HTTP Host:  static.ak.fbcdn.net                                          */
/*    Generated:  July 5th 2009 7:33:44 PM PDT                                 */
/*      Machine:  10.16.139.108                                                */
/*       Source:  Backing Store                                                */
/*     Location:  js/7efg46w6akwsow4g.pkg.js h:edah13gn                        */
/*       Locale:  en_US                                                        */
/*         Path:  js/7efg46w6akwsow4g.pkg.js                                   */
function contact_dialog_async_with_form(app_id) {
	var async = new AsyncRequest().setMethod("GET").setReadOnly(true).setData({"app_id":app_id}).setURI("/ajax/apps/contact_developer.php");
	new Dialog().setAsync(async).show();
}
function rand32() {
	return Math.floor(Math.random() * 4294967295);
}
function verifyNumber(num) {
	if (typeof num == "undefined" || isNaN(num) || num == Number.POSITIVE_INFINITY || num == Number.NEGATIVE_INFINITY) {
		num = 0;
	}
	return num;
}
function UserActivity() {
}
copy_properties(UserActivity, {_initialized:false, _listeners:[], initialize:function () {
	var activityFn = function (event) {
		Arbiter.inform(Arbiter.USER_ACTIVITY, event);
	};
	UserActivity._listeners.push(Event.listen(document.body, "mouseover", activityFn));
	var key_context = window;
	if (ua.ie()) {
		key_context = document.body;
	}
	UserActivity._listeners.push(Event.listen(key_context, "keydown", activityFn));
	UserActivity._listeners.push(Event.listen(document.body, "click", activityFn));
	UserActivity._initialized = true;
}, subscribe:function (callback) {
	if (!UserActivity._initialized) {
		UserActivity.initialize();
	}
	return Arbiter.subscribe(Arbiter.USER_ACTIVITY, callback, Arbiter.SUBSCRIBE_NEW);
}, unsubscribe:function (token) {
	Arbiter.unsubscribe(token);
}});
onloadRegister(UserActivity.initialize);
function fbpage_show_viewer_settings_dialog(fbpage_id, title) {
	var src = "/ajax/pages/viewer_settings.php?id=" + fbpage_id;
	Dialog.showFormAjax(title, src, _tx("Save"), true);
	return false;
}
function fbpage_set_fan_status(elem, fbpage_id, action_is_add, reload, handler, error_handler, extra_data) {
	handler = handler ? handler : function (asyncResponse) {
		_fbpage_show_change_status_feedback(elem, asyncResponse.getPayload());
	};
	var data = {"fbpage_id":fbpage_id, "add":action_is_add, "reload":reload};
	if (extra_data != null) {
		copy_properties(data, extra_data);
	}
	var request = new AsyncRequest().setURI("/ajax/pages/fan_status.php").setData(data).setHandler(bind(this, handle_require_email_conf_response, handler, null, null));
	if (error_handler) {
		request.setErrorHandler(error_handler);
	}
	request.send();
	return false;
}
function fbpage_set_favorite_status(elem, fbpage_id, action_is_add) {
	var handler = function () {
		_fbpage_show_change_status_feedback(elem, this.getUserData());
	};
	var data = {"fbpage_id":fbpage_id, "add":action_is_add};
	var async = new AsyncRequest().setMethod("POST").setURI("/ajax/pages/favorite_status.php").setData(data);
	new Dialog().setAsync(async).setCloseHandler(handler).show();
	return false;
}
function _fbpage_show_change_status_feedback(elem, data) {
	if (!data || !elem) {
		return;
	}
	if (data.reload) {
		goURI(URI.getRequestURI());
	} else {
		if (data.feedback) {
			var newElem = document.createElement("span");
			newElem.innerHTML = data.feedback;
			CSS.setClass(newElem, "fan_status_inactive");
			elem.parentNode.replaceChild(newElem, elem);
			var handler = function () {
				if (data.can_repeat_action) {
					newElem.parentNode.replaceChild(elem, newElem);
				}
			};
			animation(newElem).duration(3000).checkpoint().to("backgroundColor", "#FFFFFF").duration(1000).ondone(handler).go();
		}
	}
}
function fbpage_verification_reason_dialog() {
	new Dialog().setTitle(_tx("Why is this required?")).setBody(_tx("In order to upload music to your Page, we need you to submit a valid form of identification that identifies you, the admin of the Page. By submitting a valid form of identification, you are confirming that you either own the copyright to the content you will be uploading or that you are authorized by the copyright owner to upload that copyrighted content to your Page. Please note that you can black out any sensitive information on your identification if you wish, other than your name and picture. We currently only accept photo passports, school IDs, and drivers licenses.")).setButtons([Dialog.OK]).show();
	return false;
}
function pages_show_block_app(app_id, action, source) {
	var async = new AsyncRequest().setMethod("POST").setData({app_id:app_id, action:action, source:source}).setURI("/ajax/apps/block.php");
	new Dialog().setAsync(async).show();
}
function pages_change_block_wording(app_id) {
	hide("block_" + app_id);
}
function pages_promote_sms_fanning(fan, vanity_url, shortcode) {
	new Dialog().setTitle(_tx("Get more Fans through SMS")).setBody(_tx("Tell people to text \"{fan} {name}\" to {mobile-number} from their mobile phones, and they will be added as fans instantly. Standard charges may apply.", {"fan":fan, "name":vanity_url, "mobile-number":shortcode})).setButtons(Dialog.OK).show();
	return false;
}
function fbpages_app_add(app_id) {
	var async = new AsyncRequest().setURI("/ajax/apps/show_profile_add_dialog.php").setMethod("GET").setReadOnly(true).setData({profile_id:app_id});
	new Dialog().setAsync(async).show();
	return false;
}
function fbpages_app_on_add(obj) {
	var uri = "/ajax/apps/add_to_profile.php";
	var data = {profile_id:obj.profile_id, target_profile_id:obj.id};
	var handler = function () {
		ObjectBrowserController.getController(obj.element).removeItem(obj.id);
	};
	new AsyncRequest().setURI(uri).setMethod("POST").setData(data).setHandler(handler).send();
}
function CookieManager(version) {
	this.version = version;
	this.cookieName = "presence";
	this._init();
}
CookieManager.prototype = {_init:function () {
	this.storers = {};
}, register:function (subname, fn) {
	this.storers[subname] = fn;
}, store:function () {
	var cookie = this._getCookie();
	if (cookie && cookie.v && this.version < cookie.v) {
		presence.versionShutdown();
		return;
	}
	var data = {"v":this.version, "time":parseInt(presence.getTime() * 0.001)};
	for (var subname in this.storers) {
		data[subname] = this.storers[subname]();
	}
	var serialized = JSON.encode(data);
	setCookie(this.cookieName, serialized, null);
}, _getCookie:function () {
	try {
		var data = getCookie(this.cookieName);
		return data ? JSON.decode(data) : null;
	}
	catch (e) {
		return null;
	}
}, getSubCookie:function (subname) {
	var cookie = this._getCookie();
	if (!cookie) {
		return null;
	}
	return cookie[subname];
}};
var ChannelRebuildReasons = {Unknown:0, AsyncError:1, TooLong:2, Refresh:3, RefreshDelay:4, UIRestart:5, NeedSeq:6, PrevFailed:7, IFrameLoadGiveUp:8, IFrameLoadRetry:9, IFrameLoadRetryWorked:10, PageTransitionRetry:11};
function ChannelManager(user, retryInterval, channelConfig, noSubdomain) {
	this.user = user;
	this.iframeCheckTime = 16000;
	this.iframeCheckRetryTime = 16000;
	this.iframeLoadMaxRetries = 1;
	this.retryInterval = retryInterval;
	this.channelConfig = channelConfig;
	this._init(noSubdomain);
}
function handleChanneliFrameMessageEvent(event) {
	event = event || window.event;
	var domain = (event.domain || event.origin);
	if (domain.substring(domain.length - 13) != ".facebook.com" && domain.substring(domain.length - 15) != "://facebook.com" && domain != "facebook.com") {
		return;
	}
	handleChanneliFrameMessage(event.data);
}
function handleChanneliFrameMessage(iframeMsgStr) {
	if (iframeMsgStr && iframeMsgStr.charAt(0) == "{") {
		channelManager.handleiFrameMessage(eval("(" + iframeMsgStr + ")"));
	}
}
ChannelManager.prototype = {_init:function (noSubdomain) {
	this.channels = {};
	this.iframeHost = this.iframePort = null;
	this.isActionRequest = true;
	this.isReady = false;
	this.isRebuilding = false;
	this.iframeIsLoaded = false;
	this.iframeEverLoaded = false;
	this.iframeCheckFailedCount = 0;
	this.permaShutdown = false;
	this.shouldClearSubdomain = false;
	this.subframe = ge("channel_iframe");
	this.postMessage = null;
	var channelData = presenceCookieManager.getSubCookie("ch");
	if (noSubdomain) {
		this.iframeSubdomain = null;
	} else {
		this.iframeSubdomain = 0;
		if (channelData && channelData.sub) {
			for (var i = 0; i < channelData.sub.length; i++) {
				if (!channelData.sub[i]) {
					this.iframeSubdomain = i;
					break;
				}
			}
			if (i == channelData.sub.length) {
				this.iframeSubdomain = channelData.sub.length;
			}
		}
	}
	var safari = ua.safari();
	this.pollForMessages = (safari > 523 && safari < 525);
	this.useRandomSubdomain = !!ua.ie();
	if (window.postMessage) {
		if (window.addEventListener) {
			window.addEventListener("message", handleChanneliFrameMessageEvent, false);
		} else {
			window.onmessage = handleChanneliFrameMessageEvent;
		}
	} else {
		if (document.postMessage) {
			document.addEventListener("message", handleChanneliFrameMessageEvent, false);
		} else {
			Util.log("channel: no postMessage listener");
		}
	}
	presenceCookieManager.register("ch", this._getCookieInfo.bind(this));
	if (ua.firefox()) {
		onbeforeunloadRegister(this._onUnload.bind(this));
	} else {
		onunloadRegister(this._onUnload.bind(this));
	}
}, sendiFrameMessage:function (msg) {
	if (!this.postMessage) {
		return;
	}
	var msgStr = JSON.encode(msg);
	try {
		this.postMessage(msgStr, "*");
	}
	catch (e) {
		presence.error("channel: error sending message \"" + msgStr + "\" to iframe: " + e.toString());
	}
}, handleiFrameMessage:function (iframeMsg) {
	if (iframeMsg.type == "init") {
		this.iframeLoaded();
	} else {
		if (iframeMsg.type == "channelMsg") {
			this.handleChannelMsg(iframeMsg.channel, iframeMsg.seq, iframeMsg.msg);
		}
	}
}, _onUnload:function () {
	this.shouldClearSubdomain = true;
	presence.doSync(true);
}, addChannel:function (channel, seq, msgHandler, startHandler, shutdownHandler, restartHandler) {
	this.channels[channel] = {"currentSeq":seq, "nextSeq":0, "msgHandler":msgHandler, "startHandler":startHandler, "shutdownHandler":shutdownHandler, "restartHandler":restartHandler};
}, isLowestSubdomain:function () {
	var channelData = presenceCookieManager.getSubCookie("ch");
	if (!channelData || !channelData.sub) {
		return true;
	}
	for (var i = 0; i < channelData.sub.length; i++) {
		if (channelData.sub[i]) {
			return (i == this.iframeSubdomain);
		}
	}
}, _getCookieInfo:function () {
	var data = {};
	if (this.iframeHost && this.iframePort) {
		data.h = this.iframeHost;
		data.p = this.iframePort;
		if (null !== this.iframeSubdomain) {
			var channelData = presenceCookieManager.getSubCookie("ch");
			var subdomains = (channelData && channelData.sub) ? channelData.sub : [];
			var oldLength = subdomains.length;
			if (this.shouldClearSubdomain) {
				subdomains[this.iframeSubdomain] = 0;
			} else {
				subdomains[this.iframeSubdomain] = 1;
				for (var i = oldLength; i <= this.iframeSubdomain; i++) {
					if (!subdomains[i]) {
						subdomains[i] = 0;
					}
				}
			}
			data.sub = subdomains;
		}
		for (var channel in this.channels) {
			data[channel] = this.channels[channel].currentSeq;
		}
	}
	data.ri = this.retryInterval;
	return data;
}, stop:function () {
	this.stopped = true;
	this.setReady(false);
}, setReady:function (isReady) {
	this.isReady = isReady;
	var msg = {"type":"isReady", "isReady":isReady, "isActionRequest":this.isActionRequest};
	if (isReady && this.isActionRequest) {
		this.isActionRequest = false;
	}
	if (isReady) {
		msg["channels"] = this.channels;
	}
	this.sendiFrameMessage(msg);
}, setActionRequest:function (isActionRequest) {
	this.sendiFrameMessage({"type":"isActionRequest", "isActionRequest":isActionRequest});
}, iframeLoad:function (path, host, port, isReady) {
	this.isReady = isReady;
	this.iframeIsLoaded = false;
	this.iframePath = path;
	this.iframeHost = host;
	this.iframePort = port;
	var subdomain;
	if (null === this.iframeSubdomain) {
		subdomain = "";
	} else {
		subdomain = this.iframeSubdomain;
		if (this.useRandomSubdomain) {
			subdomain += "" + rand32();
		}
		subdomain += ".";
	}
	var url = "http://" + subdomain + this.iframeHost + ".facebook.com:" + this.iframePort + this.iframePath;
	setTimeout(this._iframeCheck.bind(this), this.iframeCheckTime);
	if (this.subframe.contentDocument) {
		try {
			this.subframe.contentDocument.location.replace(url);
		}
		catch (e) {
			presence.error("channel: error setting location: " + e.toString());
		}
	} else {
		if (this.subframe.contentWindow) {
			this.subframe.src = url;
		} else {
			if (this.subframe.document) {
				this.subframe.src = url;
			} else {
				presence.error("channel: error setting subframe url");
			}
		}
	}
	presence.debug("channel: done with iframeLoad, subframe sent to " + url);
}, iframeLoaded:function () {
	if (!this.iframeIsLoaded) {
		this.iframeIsLoaded = true;
		if (window.postMessage) {
			if ("object" == typeof window.postMessage) {
				var target = this.subframe.contentWindow;
				this.postMessage = function (message, origin) {
					target.postMessage(message, origin);
				};
			} else {
				this.postMessage = bind(this.subframe.contentWindow, this.subframe.contentWindow.postMessage);
			}
		} else {
			if (document.postMessage) {
				this.postMessage = bind(this.subframe.contentDocument, this.subframe.contentDocument.postMessage);
			} else {
				this.postMessage = bind(this.subframe.contentWindow, this.subframe.contentWindow.handleChannelParentMessage);
			}
		}
		this.setReady(this.isReady);
		if (this.pollForMessages) {
			this.msgCheckInterval = setInterval(this.handleChannelMsgCheck.bind(this), 100);
		}
		if (this.iframeCheckFailedCount) {
			for (var c in this.channels) {
				this.channels[c].restartHandler(false);
			}
			this._sendDummyReconnect(ChannelRebuildReasons.IFrameLoadRetryWorked);
		} else {
			for (var c in this.channels) {
				this.channels[c].startHandler();
			}
		}
		this.iframeCheckFailedCount = 0;
		this.iframeEverLoaded = true;
	}
}, _iframeCheck:function () {
	if (!this.iframeIsLoaded) {
		presence.error("channel: uplink iframe never loaded; shutting down");
		this.iframeCheckFailedCount++;
		this.iframeHost = this.iframePort = 0;
		presenceCookieManager.store();
		if (this.iframeCheckFailedCount <= this.iframeLoadMaxRetries) {
			this.iframeCheckTime = this.iframeCheckRetryTime;
			this.iframePath = null;
			this.rebuild(ChannelRebuildReasons.IFrameLoadRetry);
		} else {
			for (var c in this.channels) {
				this.channels[c].shutdownHandler();
			}
			this._sendDummyReconnect(ChannelRebuildReasons.IFrameLoadGiveUp);
		}
	} else {
		this.retryInterval = 0;
		presence.debug("channel: uplink iframe loaded fine");
	}
}, _sendDummyReconnect:function (reason) {
	var areq = new AsyncRequest().setURI("/ajax/presence/reconnect.php").setData({reason:reason, iframe_loaded:this.iframeEverLoaded}).setOption("suppressErrorHandlerWarning", true).setMethod("GET").setReadOnly(true).disableNectar();
	areq.specifiesWriteRequiredParams() && areq.send();
}, _rebuildResponse:function (response) {
	var rebuildInfo = response.getPayload();
	var channel = rebuildInfo.user_channel;
	presence.debug("got rebuild response with channel " + channel + ", seq " + rebuildInfo.seq + ", host " + rebuildInfo.host + ", port " + rebuildInfo.port);
	this.channels[channel].currentSeq = rebuildInfo.seq;
	this.channels[channel].nextSeq = 0;
	this.isRebuilding = false;
	if (rebuildInfo.path != this.iframePath || rebuildInfo.host != this.iframeHost || rebuildInfo.port != this.iframePort) {
		this.iframeLoad(rebuildInfo.path, rebuildInfo.host, rebuildInfo.port, true);
	} else {
		this.setReady(true);
	}
	presenceCookieManager.store();
	presenceUpdater.pauseUpdate();
	if (typeof chatOptions != "undefined") {
		chatOptions.setVisibility(rebuildInfo.visibility);
	}
	for (var c in this.channels) {
		this.channels[c].restartHandler(true);
	}
	presenceUpdater.resumeUpdate(["buddy_list"]);
}, _retryRebuild:function (reason) {
	if (this.retryInterval == 0) {
		this.retryInterval = this.channelConfig.MIN_RETRY_INTERVAL;
	} else {
		this.retryInterval *= 2;
		if (this.retryInterval >= this.channelConfig.MAX_RETRY_INTERVAL) {
			this.retryInterval = this.channelConfig.MAX_RETRY_INTERVAL;
		}
	}
	var randInterval = this.retryInterval * (0.75 + Math.random() * 0.5);
	presence.warn("manager trying again in " + (randInterval * 0.001) + " secs");
	setTimeout(this._rebuildSend.bind(this, reason), this.retryInterval);
}, _rebuildError:function (reason, response) {
	for (var c in this.channels) {
		this.channels[c].shutdownHandler(true);
	}
	presence.error("got rebuild error: " + response.getErrorDescription());
	if (presence.checkLoginError(response) || presence.checkMaintenanceError(response)) {
		presence.warn("manager not trying again");
	} else {
		this._retryRebuild(ChannelRebuildReasons.PrevFailed);
	}
}, _rebuildTransportError:function (reason, response) {
	for (var c in this.channels) {
		this.channels[c].shutdownHandler(true);
	}
	presence.error("got rebuild transport error: " + response.getErrorDescription());
	this._retryRebuild(reason);
}, _rebuildSend:function (reason) {
	if (typeof reason != "number") {
		reason = ChannelRebuildReasons.Unknown;
	}
	presence.debug("channel: sending rebuild");
	var areq = new AsyncRequest().setURI("/ajax/presence/reconnect.php").setData({reason:reason, iframe_loaded:this.iframeEverLoaded}).setHandler(this._rebuildResponse.bind(this)).setErrorHandler(this._rebuildError.bind(this, reason)).setTransportErrorHandler(this._rebuildTransportError.bind(this, reason)).setOption("suppressErrorAlerts", true).setMethod("GET").setReadOnly(true).disableNectar();
	return areq.specifiesWriteRequiredParams() && areq.send();
}, rebuild:function (reason) {
	if (this.stopped) {
		return;
	}
	if (this.isRebuilding) {
		presence.debug("channel: rebuild called, but already rebuilding");
		return;
	}
	this.setReady(false);
	this.isRebuilding = true;
	presence.debug("channel: rebuilding");
	if (reason == ChannelRebuildReasons.RefreshDelay) {
		this.retryInterval = this.channelConfig.MAX_RETRY_INTERVAL;
	}
	setTimeout(this._rebuildSend.bind(this, reason), this.retryInterval);
}, handleChannelMsgCheck:function () {
	if (this.pendingMsg) {
		this._handleChannelMsg(this.pendingMsg.channel, this.pendingMsg.seq, this.pendingMsg.msg);
		this.pendingMsg = null;
	}
}, handleChannelMsg:function (channel, seq, msg) {
	if (this.pollForMessages) {
		this.pendingMsg = {channel:channel, seq:seq, msg:msg};
	} else {
		this._handleChannelMsg(channel, seq, msg);
	}
}, _handleChannelMsg:function (channel, seq, msg) {
	if (msg.type == "shutdown" || msg.type == "permaShutdown") {
		if (!window.loaded || this.permaShutdown) {
			return;
		}
		if (msg.type == "permaShutdown") {
			presence.warn("channel: got permaShutdown for all channels");
			this.permaShutdown = true;
		} else {
			presence.warn("channel: got shutdown for all channels");
			this.rebuild(msg.reason);
		}
		for (var c in this.channels) {
			this.channels[c].shutdownHandler(true);
		}
	} else {
		this.channels[channel].currentSeq++;
		var nextSeq;
		if ((nextSeq = this.channels[channel].nextSeq) && seq < nextSeq) {
			presence.warn("ignoring a duplicate message (" + seq + ")<(" + nextSeq + ") on " + channel);
			return;
		}
		this.channels[channel].nextSeq = parseInt(seq) + 1;
		presence.pauseSync();
		try {
			this.channels[channel].msgHandler(channel, msg);
		}
		catch (e) {
			presence.error("error in channel handlers: " + e.toString() + ", msg: " + msg);
		}
		presence.resumeSync();
	}
}};
function LiveMessageReceiver(eventName) {
	this.eventName = eventName;
	this.subs = null;
	this.handler = bagofholding;
	this.shutdownHandler = null;
	this.restartHandler = null;
	this.registered = false;
	this.appId = 1;
}
LiveMessageReceiver.prototype.setAppId = function (appId) {
	this.appId = appId;
	return this;
};
LiveMessageReceiver.prototype.setHandler = function (handler) {
	this.handler = handler;
	this._dirty();
	return this;
};
LiveMessageReceiver.prototype.setRestartHandler = function (restartHandler) {
	this.restartHandler = restartHandler.shield();
	this._dirty();
	return this;
};
LiveMessageReceiver.prototype.setShutdownHandler = function (shutdownHandler) {
	this.shutdownHandler = shutdownHandler.shield();
	this._dirty();
	return this;
};
LiveMessageReceiver.prototype._dirty = function () {
	if (this.registered) {
		this.unregister();
		this.register();
	}
};
LiveMessageReceiver.prototype.register = function () {
	var wrapper = function (type, message) {
		return this.handler(message);
	}.bind(this);
	var type = Presence.getAppMessageType(this.appId, this.eventName);
	this.subs = {};
	this.subs["main"] = Arbiter.subscribe(type, wrapper);
	if (this.shutdownHandler) {
		this.subs["shut"] = Arbiter.subscribe(Presence.SHUTDOWN, this.shutdownHandler);
	}
	if (this.restartHandler) {
		this.subs["restart"] = Arbiter.subscribe(Presence.RESTARTED, this.restartHandler);
	}
	this.registered = true;
	return this;
};
LiveMessageReceiver.prototype.unregister = function () {
	if (!this.subs) {
		return this;
	}
	for (var k in this.subs) {
		if (this.subs[k]) {
			Arbiter.unsubscribe(this.subs[k]);
		}
	}
	this.subs = null;
	this.registered = false;
	return this;
};
LiveMessageReceiver.route = function (message) {
	var informHandler = function (response) {
		var type = Presence.getAppMessageType(message.app_id, message.event_name);
		Arbiter.inform(type, response, Arbiter.BEHAVIOR_PERSISTENT);
	};
	if (message.hasCapture) {
		new AsyncRequest().setHandler(function (r) {
			informHandler(r.getPayload());
		}).handleResponse(message.response);
	} else {
		informHandler(message.response);
	}
};
function Presence(user, name, firstName, serverTime, popoutType, sitevars) {
	this.user = user;
	this.name = name;
	this.firstName = firstName;
	this.sitevars = sitevars;
	this.popoutURL = env_get("www_base") + "presence/popout.php";
	var viewportDimensions = Vector2.getViewportDimensions();
	this.maxTabOffset = 66;
	if (ge("intern_bookmark_frame")) {
		this.maxTabOffset += Vector2.getElementDimensions($("intern_bookmark_frame")).y;
	}
	this.maxTabHeight = viewportDimensions.y - this.maxTabOffset;
	this.updateServerTime(serverTime);
	this.pageLoadTime = this.getTime();
	this._init(popoutType);
}
copy_properties(Presence, {STARTED:"presence/started", SHUTDOWN:"presence/shutdown", RESTARTED:"presence/restarted", WINDOW_RESIZED:"presence/window-resized", TAB_CLOSED:"presence/tab-closed", TAB_OPENED:"presence/tab-opened", getAppMessageType:function (appid, event_name) {
	return "presence/app_message:" + appid + ":" + event_name;
}, getArbiterMessageType:function (event_name) {
	return "presence/message:" + event_name;
}});
Presence.prototype = {minWidth:100, minHeight:100, defWidth:600, defHeight:500, defX:30, defY:30, cookiePollTime:2000, popoutHeartbeatTime:1000, popoutHeartbeatAllowance:4000, popoutHeartbeatFirstAllowance:15000, resizeStopTime:500, shutdownDelay:5000, restartDelay:3000, POPOUT_TYPE_CHAT:1, POPOUT_TYPE_VIDEOCHAT:2, _init:function (popoutType) {
	this.stateStorers = [];
	this.stateLoaders = [];
	this.windowID = rand32() + 1;
	this.contentPaddings = {"buddy_list":77, "presence_notifications":23, "presence_applications":73};
	this.contentResized = {};
	this.holder = $("presence");
	this.holderUI = $("presence_ui");
	this.bar = $("presence_bar");
	this.popoutSidebar = ge("presence_popout_sidebar");
	this.popoutWidth = this.defWidth;
	this.popoutHeight = this.defHeight;
	this.cookiePoller = null;
	this.heartbeat = null;
	this.resizeTimeout = null;
	this.lastResized = 0;
	this.stateUpdateTime = 0;
	this.loaded = false;
	this.isShutdown = false;
	this.isShuttingDown = false;
	this.isRestarting = false;
	this.isPermaShutdown = false;
	this.shutdownTime = 0;
	this.popoutClicked = false;
	this.popinClicked = false;
	this.justPoppedOut = false;
	this.disableTabAutoClose = 0;
	this.syncPaused = 0;
	this.disableUnfocus = null;
	this.tempTabCloseHandler = null;
	this.inPopoutWindow = popoutType == this.POPOUT_TYPE_CHAT;
	this.inVideoChat = popoutType == this.POPOUT_TYPE_VIDEOCHAT;
	this.inVideoChatWith = null;
	this.poppedOut = this.inPopoutWindow;
	presenceCookieManager.register("state", this._getCookieData.bind(this));
	if (this.inPopoutWindow) {
		Util.fallbackErrorHandler = null;
		if (!this.inVideoChat) {
			this.bar.style.marginRight = "200px";
		}
		if (!this.inVideoChat) {
			onbeforeunloadRegister(this.popin.bind(this, false));
			onunloadRegister(this.popin.bind(this, false));
		}
	}
	Event.listen(window, "resize", this._windowOnResize.bind(this));
	Event.listen(window, "keypress", this._documentKeyPress.bind(this));
	Event.listen(document, "click", this._documentOnClick.bind(this));
	if (DOMScroll.usingScrollWrapper()) {
		DOMScroll.registerScrollChangeHandler(this._handleScrollChange.bind(this));
	}
	Arbiter.subscribe(Arbiter.PAGE_TRANSITION, this.checkRebuild.bind(this));
	var safari = ua.safari();
	this.isSafari2 = (safari && safari < 500);
	this.isOpera = (ua.opera() > 0);
	var ff = ua.firefox();
	this.isFF2 = (ff && ff < 3);
	this.isWindows = ua.windows();
	this.load();
	this._windowOnResize.bind(this).defer();
	if (this.inPopoutWindow) {
		setTimeout(this._windowOnResize.bind(this), 3000);
	}
}, updateServerTime:function (serverTime) {
	this.timeSkew = (new Date()).getTime() - serverTime;
}, getTime:function () {
	return (new Date()).getTime() - this.timeSkew;
}, debug:function (msg) {
}, warn:function (msg) {
	Util.warn("chirp: " + msg);
}, error:function (msg) {
	Util.error("chirp: " + msg);
}, inVideoCallTo:function (to) {
	this.inVideoChatWith = to;
}, load:function () {
	var presenceState = presenceCookieManager.getSubCookie("state");
	if (!presenceState) {
		this.debug("presence: got null state cookie, loading with current state");
		this._load(this._getCookieData());
		return;
	}
	try {
		this._load(presenceState);
	}
	catch (e) {
		this.error("presence: got load exception: " + e.toString());
		this._load(this._getCookieData());
	}
}, _load:function (presenceState) {
	this.syncPaused++;
	this.stateUpdateTime = verifyNumber(presenceState.ut);
	this.popoutTime = verifyNumber(presenceState.pt);
	this.popoutWidth = verifyNumber(presenceState.w);
	this.popoutHeight = verifyNumber(presenceState.h);
	if (!this.popoutWidth) {
		this.popoutWidth = this.defWidth;
	}
	if (!this.popoutWidth) {
		this.popoutWidth = this.defHeight;
	}
	this.popoutWidth = Math.max(this.popoutWidth, this.minWidth);
	this.popoutHeight = Math.max(this.popoutHeight, this.minHeight);
	this.poppedOut = !!presenceState.p;
	if (this.poppedOut) {
		if (this.inPopoutWindow) {
			if (!this.heartbeat && !this.inVideoChat) {
				this.heartbeat = setInterval(this._popoutHeartbeat.bind(this), this.popoutHeartbeatTime);
			}
		} else {
			CSS.addClass(this.holder, "popped_out");
		}
	} else {
		if (!this.inVideoChat) {
			if (this.inPopoutWindow) {
				if (!this.loaded) {
					this.poppedOut = true;
					this.doSync();
				} else {
					if (!this.popinClicked) {
						window.close();
					} else {
					}
				}
			} else {
				this.justPoppedOut = true;
			}
			CSS.removeClass(this.holder, "popped_out");
		}
	}
	if (!this.inPopoutWindow && !this.cookiePoller) {
		this.cookiePoller = setInterval(this._pollCookie.bind(this), this.cookiePollTime);
	}
	this.virtPopoutWidth = this.popoutWidth;
	this.virtPopoutHeight = this.popoutHeight;
	this.state = presenceState;
	for (var i = 0; i < this.stateLoaders.length; i++) {
		this.stateLoaders[i](presenceState);
	}
	this._handleResize.bind(this, 0, 0).defer();
	setTimeout(this._handleResize.bind(this, 0, 0), 100);
	this.syncPaused--;
	this.loaded = true;
}, _pollCookie:function () {
	var presenceState = presenceCookieManager.getSubCookie("state");
	if (!presenceState) {
		return;
	}
	var myPopoutTime = this.popoutTime;
	if (presenceState.ut > this.stateUpdateTime) {
		this.load(presenceState);
		return;
	}
	if (this.poppedOut && !this.inPopoutWindow) {
		var cookiePopoutTime = verifyNumber(presenceState.pt);
		var diff = (new Date()).getTime() - cookiePopoutTime;
		var diffAllowance = this.popoutHeartbeatTime + this.popoutHeartbeatAllowance;
		if (this.justPoppedOut) {
			if (cookiePopoutTime == myPopoutTime) {
				diffAllowance += this.popoutHeartbeatFirstAllowance;
			} else {
				this.justPoppedOut = false;
			}
		}
		this.popoutTime = cookiePopoutTime;
		if (diff > diffAllowance) {
			this.poppedOut = false;
			this.doSync();
		}
	}
}, _popoutHeartbeat:function () {
	this._pollCookie();
	if (this.poppedOut) {
		presenceCookieManager.store();
	}
}, _getCookieData:function () {
	var presenceState = {p:this.poppedOut ? 1 : 0, w:this.popoutWidth, h:this.popoutHeight, ut:this.stateUpdateTime, pt:this.inPopoutWindow ? (new Date()).getTime() : this.popoutTime};
	for (var i = 0; i < this.stateStorers.length; i++) {
		presenceState = this.stateStorers[i](presenceState);
	}
	this.state = presenceState;
	return this.state;
}, doSync:function (immediate) {
	if (this.syncPaused) {
		return;
	}
	if (immediate) {
		this._doSync();
	} else {
		this._doSync.bind(this).defer();
	}
}, _doSync:function () {
	this.stateUpdateTime = (new Date()).getTime();
	presenceCookieManager.store();
	this._load(this.state);
}, pauseSync:function () {
	this.syncPaused++;
}, resumeSync:function () {
	this.syncPaused--;
	this.doSync();
}, handleMsg:function (channel, obj) {
	this._handleMsg.bind(this, channel, obj).defer();
}, _handleMsg:function (channel, obj) {
	if (typeof obj == "string") {
		if (obj == "shutdown") {
			this.connectionShutdown();
		} else {
			if (obj == "restart") {
				if (this.isShutdown) {
					this.restart();
				}
			}
		}
		return;
	}
	if (this.isShutdown) {
		return false;
	}
	if (!obj.type) {
		return;
	}
	if (obj.type == "app_msg") {
		LiveMessageReceiver.route(obj);
	}
	Arbiter.inform(Presence.getArbiterMessageType(obj.type), {sender:this, channel:channel, obj:obj});
}, popout:function () {
	if (this.inVideoChat) {
		return;
	}
	if (this.inPopoutWindow || this.poppedOut) {
		this.popin(true);
		return;
	}
	if (this.popoutClicked) {
		return;
	}
	this.popoutClicked = true;
	var width = this.popoutWidth;
	var height = this.popoutHeight;
	if (this.isSafari2) {
		width = this.minWidth;
		height = this.minHeight;
	}
	var w = window.open(this.popoutURL, "fbChatWindow", "status=0,toolbar=0,location=0,menubar=0," + "directories=0,resizable=1,scrollbars=0," + "width=" + width + ",height=" + height + "," + "left=" + this.defX + ",top=" + this.defY);
	if (width != this.popoutWidth || height != this.popoutHeight) {
		w.resizeBy(this.popoutWidth - width, this.popoutHeight - height);
	}
	CSS.removeClass(this.holder, "popped_out");
	this.poppedOut = true;
	this.justPoppedOut = true;
	this.popoutTime = (new Date()).getTime();
	this.doSync();
	this.popoutClicked = false;
}, popin:function (shouldClose) {
	if (this.inVideoChat) {
		return;
	}
	if (typeof shouldClose == "undefined") {
		shouldClose = true;
	}
	if (this.inPopoutWindow) {
		if (this.popinClicked) {
			return;
		}
		this.popinClicked = true;
	}
	this.poppedOut = false;
	this.doSync();
	if (this.inPopoutWindow && shouldClose) {
		window.close();
	}
}, _windowOnResize:function () {
	this.contentResized = {};
	var viewportDimensions = Vector2.getViewportDimensions();
	this._handleResize(viewportDimensions.x - this.virtPopoutWidth, viewportDimensions.y - this.virtPopoutHeight);
	if (this.inPopoutWindow) {
		clearTimeout(this.resizeTimeout);
		this.lastResized = (new Date()).getTime();
		this.resizeTimeout = setTimeout(function () {
			this.resizeTimeout = null;
			if ((new Date()).getTime() >= this.lastResized + this.resizeStopTime) {
				this._stopResize();
			}
		}.bind(this), this.resizeStopTime);
		if (viewportDimensions.x < this.popoutWidth || viewportDimensions.y < this.popoutHeight) {
			try {
				window.resizeTo(this.popoutWidth, this.popoutHeight);
				this._stopResize();
			}
			catch (e) {
			}
		}
	} else {
		this._updateMaxTabHeight();
	}
}, _updateMaxTabHeight:function () {
	this.maxTabHeight = Vector2.getViewportDimensions().y - this.maxTabOffset;
	if (DOMScroll.usingScrollWrapper() && DOMScroll.getScrollState().x) {
		this.maxTabHeight -= DOMScroll.getScrollbarSize();
	}
	if (window.buddyList && buddyList.buddyListOpen) {
		buddyList.resizeTab();
	} else {
		if (this.focusedWrapper && this.focusedContent) {
			this.tabContentResize(this.focusedWrapper, this.focusedContent);
		}
	}
}, _handleScrollChange:function (type, message) {
	if (!DOMScroll.usingScrollWrapper()) {
		return;
	}
	var scrollbarSize = DOMScroll.getScrollbarSize();
	var holderBottom = this.getHolderBottomPosition();
	var holderUIRight = 15 + (message.is_scrolled.y ? scrollbarSize : 0);
	CSS.setStyle(this.holder, "bottom", holderBottom + "px");
	CSS.setStyle(this.holderUI, "marginRight", holderUIRight + "px");
	if (typeof chatDisplay != "undefined") {
		for (var id in chatDisplay.tabs) {
			chatDisplay.tabs[id].adjustWrapperBottom();
		}
	}
	this._updateMaxTabHeight();
}, getHolderBottomPosition:function () {
	var holderBottom = 0;
	if (DOMScroll.getScrollState().x) {
		var scrollbarSize = DOMScroll.getScrollbarSize();
		holderBottom = scrollbarSize + (ua.osx() ? 1 : 0);
	}
	if (presence.isIE6) {
		holderBottom--;
	}
	return holderBottom;
}, _handleResize:function (dx, dy) {
	this.virtPopoutWidth += dx;
	this.virtPopoutHeight += dy;
	this.popoutWidth = Math.max(this.virtPopoutWidth, this.minWidth);
	this.popoutHeight = Math.max(this.virtPopoutHeight, this.minHeight);
	Arbiter.inform(Presence.WINDOW_RESIZED, {sender:this});
}, _stopResize:function () {
	if (this.virtPopoutWidth != this.popoutWidth || this.virtPopoutHeight != this.popoutHeight) {
		this.virtPopoutWidth = this.popoutWidth;
		this.virtPopoutHeight = this.popoutHeight;
		this.doSync();
	}
}, _documentKeyPress:function (e) {
	e = $E(e);
	var keycode = e ? e.keyCode : -1;
	if (keycode == KEYS.ESC) {
		Event.kill(e);
	}
}, _documentOnClick:function () {
	if (this.disableTabAutoClose) {
		return;
	}
	if ((typeof buddyList != "undefined") && buddyList.buddyListOpen) {
		if (typeof buddyListDisplay != "undefined" && buddyListDisplay.isFlyoutOpen()) {
			buddyListDisplay.closeOpenFlyout();
			return;
		}
		if (!buddyList.isSticky()) {
			buddyList.closeTab();
		}
	} else {
		this.closeTab();
	}
}, allowAutoClose:function () {
	if (this.disableTabAutoClose > 0) {
		this.disableTabAutoClose--;
	}
}, disallowAutoClose:function () {
	this.disableTabAutoClose++;
}, tabHandleMouseOver:function (tab) {
	this.disallowAutoClose();
	CSS.addClass(tab, "hover");
}, tabHandleMouseOut:function (tab) {
	this.allowAutoClose();
	CSS.removeClass(tab, "hover");
}, tabContentMouseOver:function () {
	this.disallowAutoClose();
}, tabContentMouseOut:function () {
	this.allowAutoClose();
}, _unfocus:function () {
	if (this.focusedWrapper) {
		hide(this.focusedWrapper);
	}
	if (this.focusedTab) {
		CSS.removeClass(ge(this.focusedTab), "focused");
		if (this.tempTabCloseHandler) {
			this.tempTabCloseHandler();
			this.tempTabCloseHandler = null;
		}
	}
	this.wasFocusedTab = this.focusedTab;
	this.focusedTab = this.focusedWrapper = null;
	return this.wasFocusedTab;
}, unfocus:function () {
	var wasFocusedTab = this._unfocus();
	if (wasFocusedTab) {
		this.disableUnfocus = wasFocusedTab;
		setTimeout(function () {
			this.disableUnfocus = null;
		}.bind(this), 50);
	}
}, toggleTab:function (wrapperID, tabID, scrollContentID) {
	var wrapper = ge(wrapperID);
	var tab = ge(tabID);
	if (!wrapper || !tab || tabID == this.disableUnfocus) {
		return;
	}
	if (wrapper.style.display == "none") {
		this.openTab(wrapperID, tabID, scrollContentID);
	} else {
		this.closeTab();
	}
}, closeTab:function () {
	var tab = this.focusedTab;
	if (!tab) {
		return;
	}
	var wasFocusedTab = this.wasFocusedTab;
	this.unfocus();
	CSS.removeClass(tab, "focused");
	CSS.removeClass(this.holder, "tab_open");
	Arbiter.inform(Presence.TAB_CLOSED, {sender:this, tabID:tab});
	if (tab != wasFocusedTab && wasFocusedTab == "buddy_list_tab") {
		buddyList.openTab();
	}
}, openTabDelayed:function (wrapperID, tabID, scrollContentID) {
	this.openTab.bind(this, wrapperID, tabID, scrollContentID).defer();
}, openTab:function (wrapperID, tabID, scrollContentID) {
	if (this.focusedTab == tabID) {
		return;
	}
	this._unfocus();
	this.focusedWrapper = wrapperID;
	this.focusedContent = scrollContentID;
	this.focusedTab = tabID;
	this.disableUnfocus = this.focusedTab;
	setTimeout(function () {
		this.disableUnfocus = null;
	}.bind(this), 50);
	if (scrollContentID && !this.contentResized[scrollContentID]) {
		ge(wrapperID).style.visibility = "hidden";
		show(wrapperID);
		this.tabContentResize(wrapperID, scrollContentID);
		ge(wrapperID).style.visibility = "";
	} else {
		show(wrapperID);
	}
	CSS.addClass(ge(tabID), "focused");
	CSS.addClass(this.holder, "tab_open");
	Arbiter.inform(Presence.TAB_OPENED, {sender:this, tabID:tabID});
}, contentChanged:function (contentID) {
	delete this.contentResized[contentID];
}, tabContentResize:function (wrapperID, contentID, forceLockHeight) {
	if (this.poppedOut || this.inVideoChat) {
		return;
	}
	var content = ge(contentID);
	var wrapper = ge(wrapperID);
	if (!content || !wrapper) {
		return;
	}
	var contentWrapper = content.parentNode;
	if (this.focusedWrapper == wrapperID) {
		this.contentResized[contentID] = true;
	}
	if (!this.contentPaddings[wrapperID]) {
		var dimWrapper = Vector2.getHiddenElementDimensions(wrapper);
		var dimContentWrapper = Vector2.getHiddenElementDimensions(contentWrapper);
		this.contentPaddings[wrapperID] = dimWrapper.y - dimContentWrapper.y;
	}
	if (ua.ie() < 8) {
		contentWrapper.style.height = "auto";
		dimContent = Vector2.getHiddenElementDimensions(contentWrapper);
	} else {
		dimContent = Vector2.getHiddenElementDimensions(content);
	}
	var maxContentHeight = this.maxTabHeight - this.contentPaddings[wrapperID];
	if (dimContent.y && dimContent.y < maxContentHeight) {
		CSS.removeClass(contentWrapper, "scroll");
		contentWrapper.style.height = forceLockHeight ? (dimContent.y + "px") : "auto";
	} else {
		CSS.addClass(contentWrapper, "scroll");
		contentWrapper.style.height = maxContentHeight + "px";
	}
}, pauseOffClick:function (tabID) {
	this.disableUnfocus = tabID;
}, resumeOffClick:function () {
	this.disableUnfocus = null;
}, renderLink:function (href, text, extra) {
	return "<a href=\"" + href + "\"" + (this.inPopoutWindow || this.inVideoChat ? " target=\"_blank\"" : "") + (extra ? extra : "") + ">" + text + "</a>";
}, checkRebuild:function () {
	if (this.isShutdown && !this.isPermaShutdown) {
		channelManager.rebuild(ChannelRebuildReasons.PageTransitionRetry);
	}
}, getErrorDescription:function (asyncResponse) {
	var error = asyncResponse.getError();
	var desc = asyncResponse.getErrorDescription();
	if (!desc) {
		desc = _tx("An error occurred.");
	}
	if (error == kError_Async_NotLoggedIn) {
		desc = _tx("Your session has timed out. Please login.");
	}
	return desc;
}, showAsyncError:function (asyncResponse, title) {
	if (typeof title == "undefined" || !title) {
		var chat = _tx("Chat");
		title = _tx("Facebook Chat Error");
	}
	var desc = this.getErrorDescription(asyncResponse);
	new ErrorDialog().showError(title, desc);
}, showTransportError:function (asyncResponse, title) {
	if (typeof title == "undefined" || !title) {
		var chat = _tx("Chat");
		title = _tx("Facebook Chat Error");
	}
	var desc = _tx("Could not connect to Facebook {Chat} at this time.", {"Chat":_tx("Chat")});
	new ErrorDialog().showError(title, desc);
	this.warn("presence: got async transport error: " + asyncResponse.getErrorDescription());
}, checkLoginError:function (asyncResponse) {
	var error = asyncResponse.getError();
	if (error == kError_Async_NotLoggedIn || error == kError_Async_LoginChanged || error == kError_Async_CSRFCheckFailed || error == kError_Login_GenericError) {
		this.loginShutdown();
		return true;
	}
	return false;
}, checkMaintenanceError:function (asyncResponse) {
	if (asyncResponse.getError() == 1356007) {
		this.maintenanceShutdown();
		return true;
	}
	return false;
}, permaShutdown:function () {
	this.isPermaShutdown = true;
	this.shutdown();
}, loginShutdown:function () {
	var reason = _tx("Your session has timed out. Please login.");
	this.shutdown(false, reason);
}, connectionShutdown:function (shouldDelay) {
	var reason = _tx("Could not connect to Facebook {Chat} at this time.", {"Chat":_tx("Chat")});
	this.shutdown(shouldDelay, reason);
}, maintenanceShutdown:function () {
	var reason = _tx("Facebook {Chat} is down for maintenance at this time.", {"Chat":_tx("Chat")});
	this.shutdown(false, reason);
	channelManager.stop();
}, versionShutdown:function () {
	var reason = _tx("Please refresh the page to get the latest version of Facebook {Chat}.", {"Chat":_tx("Chat")});
	this.shutdown(false, reason);
	channelManager.stop();
}, shutdown:function (shouldDelay, reason) {
	this.isRestarting = false;
	this.isShuttingDown = true;
	var now = (new Date()).getTime();
	this.shutdownTime = now;
	if (!shouldDelay) {
		this._shutdown(reason, 0);
	} else {
		setTimeout(this._shutdown.bind(this, reason, now), this.shutdownDelay);
	}
}, _shutdown:function (reason, shutdownTime) {
	if (!this.isShuttingDown && shutdownTime == this.shutdownTime) {
		return;
	}
	if (shutdownTime && this.isShutdown) {
		return;
	}
	if (typeof reason != "string" || !reason) {
		reason = _tx("Facebook {Chat} is experiencing technical problems.", {"Chat":_tx("Chat")});
	}
	if (!this.inPopoutWindow) {
		CSS.addClass(this.holder, "presence_error");
		set_inner_html($("presence_error_reason"), reason);
	} else {
		if (this.shutdownErrorDialog) {
			this.shutdownErrorDialog.hide();
		}
		this.shutdownErrorDialog = new ErrorDialog().setTitle(_tx("Facebook Chat Error")).setBody(reason).show();
	}
	if (this.isShutdown) {
		return;
	}
	this.warn("presence: shutting down");
	this.isShutdown = true;
	Arbiter.inform(Presence.SHUTDOWN, {sender:this});
}, restart:function (shouldDelay) {
	this.isShuttingDown = false;
	this.isRestarting = true;
	if (!shouldDelay) {
		this._restart(0);
	} else {
		setTimeout(this._restart.bind(this, this.shutdownTime), this.restartDelay);
	}
}, _restart:function (shutdownTime) {
	if (!this.isRestarting || (shutdownTime && shutdownTime != this.shutdownTime)) {
		return;
	}
	this.debug("presence: restarting");
	this.isShutdown = false;
	this.load();
	Arbiter.inform(Presence.RESTARTED, {sender:this});
	if (!this.inPopoutWindow) {
		CSS.removeClass(this.holder, "presence_error");
	} else {
		if (this.shutdownErrorDialog) {
			this.shutdownErrorDialog.hide();
		}
	}
}, start:function () {
	Arbiter.inform(Presence.STARTED, {sender:this});
}, registerStateStorer:function (fn) {
	this.stateStorers.push(fn);
}, registerStateLoader:function (fn) {
	this.stateLoaders.push(fn);
}, registerTempTabCloseHandler:function (handler) {
	this.tempTabCloseHandler = handler;
}};
function getFirstName(name) {
	var words = name.split(" ");
	var fname = words[0];
	var flen = fname.length;
	if (typeof words[1] != "undefined" && (flen == 1 || (flen == 2 && fname.indexOf(".") != -1) || (flen == 3 && fname.toLowerCase() == "the"))) {
		fname += " " + words[1];
	}
	return fname;
}
function PresenceUpdater() {
	this.timerGranularity = presence.sitevars.UPDATE_GRANULARITY ? presence.sitevars.UPDATE_GRANULARITY * 1000 : 60000;
	this._init();
}
PresenceUpdater.prototype = {_init:function () {
	this.handlers = [];
	this.updatePaused = 0;
	this.updateNumber = 0;
	this._runTimer();
}, register:function (asyncParam, checkCB, responseCB, errorCB, transportErrorCB) {
	this.handlers.push({"asyncParam":asyncParam, "checkCB":checkCB, "responseCB":responseCB, "errorCB":errorCB, "transportErrorCB":transportErrorCB});
}, _runTimer:function () {
	clearTimeout(this.timer);
	this.timer = setTimeout(this.checkForUpdate.bind(this, false, [], false), this.timerGranularity);
}, forceUpdate:function (handlers) {
	if (this.updatePaused) {
		return;
	}
	if (handlers !== undefined && handlers.length > 0) {
		this.checkForUpdate(false, handlers, false);
	} else {
		this.checkForUpdate(true, [], false);
	}
}, pauseUpdate:function () {
	this.updatePaused++;
}, resumeUpdate:function (handlers) {
	this.updatePaused--;
	this.forceUpdate(handlers);
}, checkForUpdate:function (forceAll, forceHandlers, bypassTimer) {
	if (!bypassTimer) {
		clearTimeout(this.timer);
	}
	if (presence.isShutdown) {
		if (!bypassTimer) {
			this._runTimer();
		}
		return;
	}
	var time = presence.getTime();
	var asyncHandlers = [];
	var asyncData = {user:presence.user};
	for (var i = 0; i < this.handlers.length; i++) {
		var handlerInfo = this.handlers[i];
		var forceUpdate = forceAll || (forceHandlers.indexOf(handlerInfo.asyncParam) != -1);
		var shouldUpdate = handlerInfo.checkCB(time, asyncData, forceUpdate);
		if (shouldUpdate) {
			asyncData[handlerInfo.asyncParam] = 1;
			asyncHandlers.push(handlerInfo);
		}
	}
	if (asyncHandlers.length > 0) {
		this._sendUpdate(asyncData, asyncHandlers, bypassTimer);
	} else {
		if (!bypassTimer) {
			this._runTimer();
		}
	}
}, runHandler:function (asyncHandler) {
	this.checkForUpdate(false, [asyncHandler], true);
}, _initialHandler:function (updateNumber, response) {
	if (updateNumber != this.updateNumber) {
		return false;
	}
}, _onResponse:function (asyncHandlers, bypassTimer, response) {
	var updateInfo = response.getPayload();
	presence.updateServerTime(updateInfo.time);
	var updateTime = presence.getTime();
	for (var i = 0; i < asyncHandlers.length; i++) {
		var handler = asyncHandlers[i];
		var paramResult = updateInfo[handler.asyncParam];
		if (typeof paramResult == "undefined" || !paramResult) {
			handler.errorCB(response);
		} else {
			handler.responseCB(paramResult, updateTime);
		}
	}
	presenceCookieManager.store();
	if (!bypassTimer) {
		this._runTimer();
	}
}, _onError:function (asyncHandlers, response) {
	for (var i = 0; i < asyncHandlers.length; i++) {
		asyncHandlers[i].errorCB(response);
	}
	this._runTimer();
}, _onTransportError:function (asyncHandlers, response) {
	for (var i = 0; i < asyncHandlers.length; i++) {
		asyncHandlers[i].transportErrorCB(response);
	}
	this._runTimer();
}, _sendUpdate:function (asyncData, asyncHandlers, bypassTimer) {
	this.updateNumber++;
	var uri = asyncData["notifications"] ? "/ajax/presence/update.php" : "/ajax/chat/buddy_list.php";
	var request_data = URI.getRequestURI().getQueryData();
	var query_data = {};
	for (key in request_data) {
		if (key.indexOf("buddy") == 0) {
			query_data[key] = request_data[key];
		}
	}
	if (query_data) {
		uri = new URI(uri).setQueryData(query_data);
	}
	this.async = new AsyncRequest().setInitialHandler(this._initialHandler.bind(this, this.updateNumber)).setHandler(this._onResponse.bind(this, asyncHandlers, bypassTimer)).setErrorHandler(this._onError.bind(this, asyncHandlers)).setTransportErrorHandler(this._onTransportError.bind(this, asyncHandlers)).setOption("suppressErrorAlerts", true).setData(asyncData).disableNectar().setURI(uri).send();
}};
function ChatNotifications(count, countNew, updateTime, app_names, latest_notif, latest_read_notif) {
	this.count = count;
	this.countNew = countNew;
	this.updateTime = updateTime;
	this.user = presence.user;
	this.app_names = app_names;
	this.merged_alert_ids = {};
	this.merged_mouseover_handler = null;
	this.latest_notif_time = latest_notif;
	this.latest_read_notif_time = latest_read_notif;
	this._init();
}
copy_properties(ChatNotifications, {showReportDialog:function (applicationName, hideHandler, reportHandler, cancelHandler) {
	var hide_button = {name:"hide", label:_tx("Hide all"), handler:hideHandler};
	var report_button = {name:"report", label:_tx("Report Spam"), handler:reportHandler};
	var cancel_button = {};
	copy_properties(cancel_button, Dialog.CANCEL);
	cancel_button.handler = cancelHandler;
	new Dialog().setTitle(_tx("Do you want to hide all notifications from {application-name}?", {"application-name":applicationName})).setBody(_tx("This will hide all notifications from this application. ")).setButtons([hide_button, report_button, cancel_button]).setModal().show();
}, markAppNotificationSpam:function (applicationId, platformType, isSpamReport) {
	var params = {app_id:applicationId, collapse:1, type:platformType};
	if (isSpamReport) {
		params.spam = 1;
	}
	new AsyncSignal("/ajax/notifications.php", params).send();
}, UPDATER_NAME:"notifications"});
copy_properties(ChatNotifications.prototype, {_init:function () {
	this.cookieName = "notifications_" + this.user;
	this.markReadAsync = null;
	this.markupCached = null;
	this.beepsExpiredToken = null;
	this.appHideCache = [];
	this.updateCheckCount = 0;
	this.wrapperID = "presence_notifications";
	this.contentID = "presence_notifications_content";
	this.content = ge(this.contentID);
	this.countSpan = ge("presence_notifications_count");
	this.navInbox = ge("nav_inbox");
	this._updateCount();
	Arbiter.subscribe(Presence.getArbiterMessageType("notification"), this._handleNotificationMsg.bind(this));
	Arbiter.subscribe(Presence.getArbiterMessageType("notifications_read"), this._handleNotificationsReadMsg.bind(this));
	presenceUpdater.register(ChatNotifications.UPDATER_NAME, this._checkUpdater.bind(this), this._onUpdaterResponse.bind(this), this._onUpdaterError.bind(this), this._onUpdaterError.bind(this));
	presenceCookieManager.register("ntf", this._getCookieData.bind(this));
}, notifyRead:function (alertsRead) {
	var data = null;
	if (alertsRead) {
		data = {alert_ids:alertsRead};
	}
	AsyncRequest.pingURI("/ajax/presence/notifications_read.php", data);
}, markRead:function (skipAsyncRequest, alertsRead, numUnread) {
	if (this.countNew == 0) {
		return;
	}
	this.countNew = numUnread ? numUnread : 0;
	this._updateCount();
	if (!skipAsyncRequest) {
		this.notifyRead(alertsRead);
	}
	var unreads = [];
	if (alertsRead) {
		for (var i = 0; i < alertsRead.length; i++) {
			var element_id = "div#notification_" + alertsRead[i] + ".notif_unread";
			var match = DOM.scry(this.content, element_id);
			if (match.length == 1) {
				unreads.push(match[0]);
			}
		}
	} else {
		unreads = DOM.scry(this.content, "div.notif_unread");
	}
	for (var i = 0; i < unreads.length; i++) {
		animation(unreads[i]).duration(1250).checkpoint().to("backgroundColor", "#FFFFFF").duration(2250).ondone(CSS.removeClass.bind(null, unreads[i], "notif_unread")).go();
	}
}, _getCookieData:function () {
	return this.countNew;
}, requiresUpdate:function (time, asyncData, forceUpdate) {
	if (!buddyList._checkUpdater(time, {}, forceUpdate)) {
		return false;
	}
	if (asyncData && undefined != asyncData[ChatNotifications.UPDATER_NAME]) {
		return asyncData[ChatNotifications.UPDATER_NAME];
	}
	return forceUpdate || ((100 / (this.updateCheckCount + 1)) <= presence.sitevars.NOTIFICATIONS_PIGGYBACK_PERCENTAGE);
}, _checkUpdater:function (time, asyncData, forceUpdate) {
	if (!buddyList._checkUpdater(time, {}, forceUpdate)) {
		return false;
	}
	if (this.requiresUpdate(time, {}, forceUpdate)) {
		this.updateCheckCount = 0;
		asyncData["notif_latest"] = this.latest_notif_time;
		asyncData["notif_latest_read"] = this.latest_read_notif_time;
		asyncData[ChatNotifications.UPDATER_NAME] = 1;
		return true;
	} else {
		this.updateCheckCount++;
		asyncData[ChatNotifications.UPDATER_NAME] = 0;
	}
	return false;
}, _updateInboxMarkup:function (inboxCount, inboxDropdownMarkup) {
	if (this.navInbox && inboxCount != null) {
		CounterDisplay.setCount("messages_unread", inboxCount);
	}
	var inboxDropdownElement = ge("fb_menu_inbox_dropdown");
	if (inboxDropdownElement && inboxDropdownMarkup) {
		inboxDropdownElement.setContent(HTML(inboxDropdownMarkup));
	}
}, _onUpdaterResponse:function (notificationResponse, time) {
	this._updateInboxMarkup(notificationResponse.inboxCount, notificationResponse.inboxDropdownMarkup);
	if (!notificationResponse.no_change) {
		if (this.count != notificationResponse.count) {
			this.count = notificationResponse.count;
			presence.contentChanged(this.contentID);
		}
		this.countNew = notificationResponse.countNew;
		this.updateTime = time;
		this.latest_notif_time = notificationResponse.latest_notif;
		this.latest_read_notif_time = notificationResponse.latest_read_notif;
		this._addAppNames(notificationResponse.app_names);
		var multiple_updates = (null != this.markupCached);
		this.markupCached = notificationResponse.markup;
		if (presence.focusedTab == "presence_notifications_tab") {
			multiple_updates || presence.registerTempTabCloseHandler(this._updateDisplayDelayed.bind(this));
		} else {
			this._updateDisplayDelayed();
		}
		Arbiter.inform(Arbiter.NEW_NOTIFICATIONS, notificationResponse);
	}
}, _updateDisplayDelayed:function () {
	if (typeof Beeper != "undefined") {
		this.beepsExpiredToken = Arbiter.subscribe(Arbiter.BEEPS_EXPIRED, this._updateDisplay.bind(this));
	} else {
		this._updateDisplay();
	}
}, _updateDisplay:function () {
	if (!this.content || !this.markupCached) {
		return;
	}
	set_inner_html(this.content, this.markupCached);
	for (var i = 0; i < this.appHideCache.length; i++) {
		this.hideNotifications(this.appHideCache[i], true);
	}
	this.markupCached = null;
	this.appHideCache = [];
	this._updateCount();
	if (this.beepsExpiredToken) {
		Arbiter.unsubscribe(this.beepsExpiredToken);
	}
}, _onUpdaterError:function (response) {
}, _updateCount:function () {
	if (this.countSpan) {
		this.countSpan.innerHTML = this.countNew ? "<strong>" + this.countNew + "</strong>" : "";
	}
}, hideNotifications:function (app_id, cached) {
	var notifs = DOM.scry(this.content, "div.notif_" + app_id);
	for (var i = 0; i < notifs.length; i++) {
		if (cached) {
			hide(notifs[i]);
		} else {
			animation(notifs[i]).to("opacity", 0).to("height", 0).blind().duration(1000).hide().go();
		}
	}
	this.count -= notifs.length;
	presence.contentChanged(this.contentID);
	if (this.count <= 0) {
		var nothing_new = ge("presence_no_notifications");
		nothing_new && show(nothing_new);
	}
	cached || this.appHideCache.push(app_id);
}, showHideDialog:function (clickedElement, app_id, platform_type) {
	var hide_handler = function (button_name) {
		this.hideNotifications(app_id);
		setTimeout(presence.allowAutoClose.bind(presence), 1100);
		var is_spam_report = ("report" == button_name);
		ChatNotifications.markAppNotificationSpam(app_id, platform_type, is_spam_report);
		(typeof (toggleType) == "function") && (typeof (hidden) != "undefined") && (!hidden[app_id]) && toggleType(app_id, true, null, false, true, presence.user, false, platform_type);
	};
	var hide_handler = bind(this, hide_handler, "hide");
	var report_handler = bind(this, hide_handler, "report");
	var cancel_handler = function () {
		presence.allowAutoClose();
	};
	var app_name = this.app_names[app_id];
	ChatNotifications.showReportDialog(app_name, hide_handler, report_handler, cancel_handler);
	presence.disallowAutoClose();
	return false;
}, _addAppNames:function (appNames) {
	appNames && copy_properties(this.app_names, appNames);
}, _mergeNotification:function (notificationId, notificationMarkup, notificationUnread, appNames) {
	var notif = HTML(notificationMarkup);
	DOM.prependContent(this.content, notif);
	this.count++;
	if (notificationUnread) {
		this.countNew++;
	}
	this._updateCount();
	appNames && this._addAppNames(appNames);
	if (presence.focusedTab == "presence_notifications_tab") {
		if (is_empty(this.merged_alert_ids)) {
			this.merged_mouseover_handler = this.content.listen("mouseover", this._markMergedRead.bind(this));
		}
		this.merged_alert_ids[notificationId] = notificationUnread;
		presence.tabContentResize(this.wrapperID, this.contentID);
	}
	(function () {
		var timestamp = DOM.find($("notification_" + notificationId), "span.time");
		DOM.setContent(timestamp, _tx("within 10 minutes"));
	}).defer(1000 * 300);
}, _markMergedRead:function () {
	this.merged_mouseover_handler.remove();
	if (!this.merged_alert_ids) {
		return;
	}
	var unread_ids = [];
	for (var alert_id in this.merged_alert_ids) {
		if (this.merged_alert_ids) {
			unread_ids.push(alert_id);
		}
	}
	this.merged_alert_ids = {};
	this.markRead(false, unread_ids);
}, _handleNotificationMsg:function (type, data) {
	var obj = data.obj;
	if (obj.markup) {
		this._mergeNotification(obj.alert_id, obj.markup, obj.unread, obj.app_names);
	} else {
		presenceUpdater.runHandler("notifications");
	}
}, _handleNotificationsReadMsg:function (type, data) {
	var obj = data.obj;
	if (typeof Beeper != "undefined") {
		Beeper.getInstance().markRead(true, obj.alert_ids);
	}
	this.markRead(true, obj.alert_ids, obj.num_unread);
}});
if (window.Bootloader) {
	Bootloader.done(["js/7efg46w6akwsow4g.pkg.js"]);
}

